<template>
  <div class="monaco-editor-container">
    <div class="title">
      {{ title }}
    </div>
    <div ref="monacoEditorRef" class="editor"></div>
  </div>
</template>
<script lang="ts" setup>
import {
  ref,
  onMounted,
  watch,
  shallowRef,
  defineEmits,
  defineProps,
} from 'vue';
import * as Monaco from 'monaco-editor';

const props = defineProps<{
  title: string;
  code: string;
}>();

const editorRef = shallowRef();
let _subscription: Monaco.IDisposable | undefined;
let __prevent_trigger_change_event = false;

const emit = defineEmits(['change']);
const monacoEditorRef = ref();
watch(
  () => props.code,
  (v) => {
    const editor = editorRef.value;
    const model = editor.getModel();
    if (v !== model.getValue()) {
      editor.pushUndoStop();
      __prevent_trigger_change_event = true;
      model.pushEditOperations(
        [],
        [
          {
            range: model.getFullModelRange(),
            text: v,
          },
        ],
      );
      editor.pushUndoStop();
      __prevent_trigger_change_event = false;
    }
  },
);
onMounted(() => {
  const monacoInstance = (editorRef.value = Monaco.editor.create(
    monacoEditorRef.value,
    {
      value: props.code,
      language: 'json',
      formatOnPaste: true,
      tabSize: 2,
      minimap: {
        enabled: false,
      },
    },
  ));
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  _subscription = monacoInstance.onDidChangeModelContent(() => {
    if (!__prevent_trigger_change_event) {
      const newValue = monacoInstance.getValue();
      emit('change', newValue);
    }
  });
});
</script>

<style scoped>
.monaco-editor-container {
  border: 1px solid #ebebeb;
}
.title {
  background: #eee;
  padding: 20px;
  border-radius: 5px;
}
.editor {
  height: 400px;
}
</style>
